package com.heima.search.service.Impl;

import com.alibaba.fastjson.JSON;

import com.heima.model.common.dtos.common.ResponseResult;
import com.heima.model.common.dtos.app.UserSearchDto;
import com.heima.model.common.enums.AppHttpCodeEnum;
import com.heima.model.user.pojos.ApUser;
import com.heima.search.service.ApUserSearchService;
import com.heima.search.service.ArticleSearchService;
import com.heima.utils.thread.AppThreadLocalUtil;
import org.apache.commons.lang3.StringUtils;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.text.Text;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.Operator;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;

@Service
public class ArticleSearchServiceImpl implements ArticleSearchService {
    @Autowired
    private RestHighLevelClient restHighLevelClient;
    @Autowired
    private ApUserSearchService apUserSearchService;
    @Override
    public ResponseResult search(UserSearchDto userSearchDto) {
        //检查参数
        if(userSearchDto==null){
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
        ApUser user = AppThreadLocalUtil.getUser();
        //异步调用保存搜索记录
        if(user!=null&&userSearchDto.getFromIndex()==0){
            apUserSearchService.insert(userSearchDto.getSearchWords(),AppThreadLocalUtil.getUser().getId());
        }
        try {
            //设置查询条件
            SearchRequest searchRequest = new SearchRequest("app_info_article");
            SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
            //关键字的分词之后查询
            BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
            if(userSearchDto.getSearchWords()!=null) {
                boolQueryBuilder.must(QueryBuilders.queryStringQuery(userSearchDto.getSearchWords()).field("title").field("content").defaultOperator(Operator.OR));
            }
            //查询小于mindate的数据
            if(userSearchDto.getMinBehotTime()!=null) {
                boolQueryBuilder.must(QueryBuilders.rangeQuery("publishTime").lt(userSearchDto.getMinBehotTime().getTime()));
            }
            //分页查询
            searchSourceBuilder.from(0);
            searchSourceBuilder.size(userSearchDto.getPageSize());
            //按发布时间倒序查询
            searchSourceBuilder.sort("publishTime", SortOrder.DESC);
            //高亮显示
            searchRequest.source().highlighter(new HighlightBuilder().field("title").preTags("<font style='color: red; font-size: inherit;'>").postTags("</font>"));
            searchSourceBuilder.query(boolQueryBuilder);
            searchRequest.source(searchSourceBuilder);
            //获取响应数据
            SearchResponse response = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
            if(response==null){
                return ResponseResult.errorResult(AppHttpCodeEnum.valueOf("查询失败"));
            }
            //解析响应数据
            SearchHits hits = response.getHits();
            //定义封装数据
            List<Map> list = new ArrayList<>();
            //获取总条数
            long total = hits.getTotalHits().value;
            //获取文档数组
            SearchHit[] hitsList = hits.getHits();
            for (SearchHit hit : hitsList) {
                String sourceAsString = hit.getSourceAsString();
                Map map = JSON.parseObject(sourceAsString, Map.class);
                Map<String, HighlightField> highlightFields = hit.getHighlightFields();
                if(!highlightFields.isEmpty()){
                    HighlightField highlightField = highlightFields.get("title");
                    if(highlightField!=null){
                        Text[] titles = highlightField.getFragments();
                        String title = StringUtils.join(titles);
                        //高亮标题
                        map.put("h_title",title);
                    }
                }else{
                    //原始标题
                    map.put("h_title",map.get("title"));
                }
                list.add(map);
            }
            return ResponseResult.okResult(list);
        }catch (Exception e){
            e.printStackTrace();
            return ResponseResult.errorResult(AppHttpCodeEnum.PARAM_INVALID);
        }
    }
}
